package com.yyoo.doc.mypdf;

import com.lowagie.text.Document;
import com.lowagie.text.pdf.PdfWriter;
import com.yyoo.doc.mypdf.sax.MyPdfSaxHandler;
import org.dom4j.io.SAXReader;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;

/**
 * html 转 pdf
 *
 * @author zzy
 *
 * 注：本工具只用于将 html 元素转换为 pdf 元素，并通过传入的 pdf document 进行操作
 * 不对 pdf document 进行关闭，在使用时请自行操作 pdf document 的创建、关闭等
 * 这意味着我们可以将多个 html 文件输出到 同一个 document 对象（同一个 pdf 文件）
 */
public class Html2Pdf {

    public static final String ERROR_MSG = "html 转 pdf 失败";

    /**
     * html 源文件的编码格式
     */
    private static Charset charset = StandardCharsets.UTF_8;

    private Html2Pdf() {
    }

    /**
     * 设置 html 源文件的编码格式
     * @param charset html 源文件的编码格式
     */
    public static void setCharset(Charset charset) {
        Html2Pdf.charset = charset;
    }

    /**
     * 将 html 转输出到 pdf
     * @param pdfWriter PdfWriter 对象
     * @param pdfDoc pdf 文档对象
     * @param htmlFilePath html 文件路径
     */
    public static void convert(PdfWriter pdfWriter,Document pdfDoc, Path htmlFilePath) {
        try {
            convert(pdfWriter,pdfDoc, Files.newInputStream(htmlFilePath), htmlFilePath.toString());
        } catch (IOException e) {
            throw new MyPdfException(ERROR_MSG,e);
        }
    }

    /**
     * 将 html 转输出到 pdf
     * @param pdfWriter PdfWriter 对象
     * @param pdfDoc pdf 文档对象
     * @param htmlUrl html 文件的 url
     * @throws IOException html 文件不存在 或 文件输入流 读取失败
     */
    public static void convert(PdfWriter pdfWriter,Document pdfDoc, URL htmlUrl) throws IOException {
        convert(pdfWriter,pdfDoc,htmlUrl.openStream(),htmlUrl.toString());
    }

    /**
     * 将 html 转输出到 pdf
     * @param pdfWriter PdfWriter 对象
     * @param pdfDoc pdf 文档对象
     * @param inputStream html 文件流
     * @param baseUri html 的基准路径（用于解析内部的 link 或 image 标签对应的链接）
     */
    public static void convert(PdfWriter pdfWriter,Document pdfDoc,InputStream inputStream, String baseUri) {

        try {
            SAXReader saxReader = new SAXReader();
            XMLReader xmlReader = saxReader.getXMLReader();
            MyPdfSaxHandler myPdfSaxHandler = new MyPdfSaxHandler(pdfWriter, pdfDoc, baseUri);
            myPdfSaxHandler.setCharSet(charset);
            xmlReader.setContentHandler(myPdfSaxHandler);
            xmlReader.parse(new InputSource(inputStream));
        } catch (IOException | SAXException e) {
            throw new MyPdfException(ERROR_MSG,e);
        }

    }

}
